#include "genagent.h"
#include <QThread>
#include <QDebug>
#include "datacollector.h"

GenAgent::GenAgent(int genId, const TGenConfig& genConfig):
	m_socket(NULL)
{
	m_genId = genId;
	m_genConfig = genConfig;
}

GenAgent::~GenAgent()
{
}

TGenConfig GenAgent::getConfig()
{
	return m_genConfig;
}

int GenAgent::getGenId()
{
	return m_genId;
}

void GenAgent::setGenId(int genId)
{
	m_genId = genId;
}

void GenAgent::setGenConfig(TGenConfig config)
{
	m_genConfig = config;
}

// slots
// initialize, run in another thread different from the constructor
void GenAgent::InitAgent()
{
	// if m_socket is not initialized
	if(m_socket == NULL){
		m_socket = new QTcpSocket();
		QObject::connect(m_socket, SIGNAL(readyRead()), this, SLOT(readReadyHandle()));
	}
	//qDebug() << "thread started" << m_socket;
}

// make sure socket connected
void GenAgent::ConnectGenerator(int genId, TGenConfig config)
{
	if(genId != m_genId) return;

	// set gen config
	m_genConfig = config;

	QString genIP(m_genConfig.ip.c_str());
	m_socket->connectToHost(genIP, GenListenPort);

	if(m_socket->waitForConnected(1000)){
		qDebug() << "GenAgent::ConnectGenerator: connected to " << QString(m_genConfig.ip.c_str());
		emit connectCompleted(m_genId, 0);
	} else {
		qDebug() << m_socket->error();
		emit connectCompleted(m_genId, 1);
	}
}

// sendCommand
void GenAgent::SendCommand(int genId, int type)
{
	// command is not mine
	if(genId != m_genId) return;
	TPacket packet;
	
	switch(type){
		case RUN_REQ:
			protocol_make_pkt(packet, type, 0, NULL, 0);
			protocol_send_pkt(m_socket, packet);
			break;
		case STOP_REQ:
			protocol_make_pkt(packet, type, 0, NULL, 0);
			protocol_send_pkt(m_socket, packet);
			break;
		default:
			qDebug() << "GenAgent::SendCommand: unknown command type";
			break;
	}
}

void GenAgent::SendProfile(TProfile profile)
{
	TPacket packet;
	profile.count = m_genConfig.userCount;
	profile.range_start = m_genId * GenRangeBase;
	profile.range_end = profile.range_start + GenRangeBase;

	int type = PROFILE_REQ;
	protocol_make_pkt(packet, type, 0, (uint8_t *)&profile, sizeof(profile));
	protocol_send_pkt(m_socket, packet);
}

// recv reply
void GenAgent::readReadyHandle()
{
	static char buffer[READ_BUFFER_SIZE];
	int count;

	if((count = m_socket->read(buffer, READ_BUFFER_SIZE)) < (int)sizeof(TPacketHeader)){
		qDebug() << "GenAgent::readReadyHandle: readReady read count < sizeof(header), count = " << count;
		qDebug() << m_socket->error();
		return;
	}
	TPacket reply;
	QList<TTranData> difTranDataList;
	TTranData tmpTranData;
	TTranData zeroTranData = {0, 0};
	int incUser;

	// handle the situation where several data pile together
	char *i;
	uint8_t *sumInfoIndex;
	int cur = 0;
	for(i = buffer; i < buffer + count; i += sizeof(TPacketHeader)){
		// extract header
		reply.header = *((PPacketHeader)(i));

		// if the packet has extra data
		if(count > (int)sizeof(TPacketHeader)){
			reply.data = (uint8_t *)(i) + sizeof(TPacketHeader);
			//reply.length = count - sizeof(TPacketHeader);
			reply.length = reply.header.length;
		} else { // doesnot contain data except the header
			reply.data = NULL;
			reply.length = 0;
		}
		// get the packet type
		int type = reply.header.head & P_TYPE_MASK;
		switch(type){
			case RUN_REP:
				emit commandCompleted(m_genId, type, protocol_get_status(reply));
				break;
			case STOP_REP:
				emit commandCompleted(m_genId, type, protocol_get_status(reply));
				break;
			case PROFILE_REP:
				emit commandCompleted(m_genId, type, protocol_get_status(reply));
				break;
			case USER_REP:
				incUser = *((int *)(reply.data));
				emit userDataArrived(m_genId, incUser);
				break;
			case SUM_REP:
				for(cur = 0, sumInfoIndex = reply.data; sumInfoIndex < reply.data + reply.length; cur ++, sumInfoIndex += sizeof(TTranData)){
					// initialize old trandata list
					if(oldTranDataList.count() < cur + 1){
						oldTranDataList.append(zeroTranData);
					}
					// the current trandata
					tmpTranData = *((PTranData)(sumInfoIndex));

					difTranDataList.append(zeroTranData);
					difTranDataList[cur].tps = tmpTranData.tps - oldTranDataList[cur].tps;
					difTranDataList[cur].resp = tmpTranData.resp - oldTranDataList[cur].resp;

					// replace old with current
					oldTranDataList[cur] = tmpTranData;
				}
				emit tranDataArrived(m_genId, difTranDataList);
				break;
			default:
				qDebug() << "GenAgent::readReadyHandle: unknown type: " << type;
				break;
		}
		i += reply.length;
	}
}
